package oc.tm.sg.admin.web.service.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import oc.tm.sg.admin.govern.BootstrapGovern;
import oc.tm.sg.admin.govern.domain.SgApplication;
import oc.tm.sg.admin.web.service.ApplicationsService;
import oc.tm.sg.registry.common.URL;

import org.smart4j.framework.tx.annotation.Service;

/**
 * 应用控制器
 * @author lry
 */
@Service
public class ApplicationsServiceImpl implements ApplicationsService {
	
	BootstrapGovern registryContainer=BootstrapGovern.INSTANCE;
    
	/**
     * 获取所有应用列表
     * @return
     */
    public List<SgApplication> getApplications() {
    	List<SgApplication> rows = new ArrayList<SgApplication>();
    	
        Set<String> applications = registryContainer.getApplications();
        if (applications != null && applications.size() > 0) {
        	SgApplication dubboApplication;
            for (String application : applications) {
                dubboApplication = new SgApplication();
                dubboApplication.setName(application);
                List<URL> providers = registryContainer.getProvidersByApplication(application);
                List<URL> consumers = registryContainer.getConsumersByApplication(application);

                if ((providers != null && providers.size() > 0) || (consumers != null && consumers.size() > 0)) {
                    URL url = (providers != null && providers.size() > 0) ? providers.iterator().next() : consumers.iterator().next();
                    dubboApplication.setName(application);//应用名称
                    dubboApplication.setOwner(url.getParameter("owner", ""));//负责人
                    dubboApplication.setOrganization((url.hasParameter("organization") ? url.getParameter("organization") : ""));//所属组织
                }

                dubboApplication.setProviderCount(providers == null ? 0 : providers.size());
                dubboApplication.setConsumerCount(consumers == null ? 0 : consumers.size());

                Set<String> efferents = registryContainer.getDependencies(application, false);
                dubboApplication.setEfferentCount(efferents == null ? 0 : efferents.size());

                Set<String> afferents = registryContainer.getDependencies(application, true);
                dubboApplication.setAfferentCount(afferents == null ? 0 : afferents.size());

                rows.add(dubboApplication);
            }
        }
        return rows;
    }

    /**
     * 根据应用获取提供者列表
     * @param application
     * @return
     */
    public List<String> getProvidersByApplication(String application) {
        List<URL> providers = registryContainer.getProvidersByApplication(application);
        List<String> rows = new ArrayList<String>();
        if (providers != null && providers.size() > 0) {
            for (URL u : providers) {
                rows.add(u.toFullString());
            }
        }
        return rows;
    }

    /**
     * 根据应用获取消费者列表
     * @param application
     * @return
     */
    public List<String> getConsumersByApplication(String application) {
        List<URL> consumers = registryContainer.getConsumersByApplication(application);
        List<String> rows = new ArrayList<String>();
        if (consumers != null && consumers.size() > 0) {
            for (URL u : consumers) {
                rows.add(u.toFullString());
            }
        }
        return rows;
    }

    /**
     * 依赖列表
     * @param application
     * @param reverse
     * @return
     */
    public List<String> dependencies(String application, boolean reverse) {
        List<String> rows = new ArrayList<String>();

        //Set<String> directly = registryContainer.getDependencies(application, reverse);
        Set<String> indirectly = new HashSet<String>();
        appendDependency(rows, reverse, application, 0, new HashSet<String>(), indirectly);

        return rows;
    }

    /**
     * 追加依赖
     * @param rows
     * @param reverse
     * @param application
     * @param level
     * @param appended
     * @param indirectly
     */
    private void appendDependency(List<String> rows, boolean reverse, String application, int level, Set<String> appended, Set<String> indirectly) {
        StringBuilder buf = new StringBuilder();
        boolean end = false;
        if (level > 5) {
            end = true;
        } else {
            buf.append(application);
            if (appended.contains(application)) {
                end = true;
            }
        }
        rows.add(buf.toString());
        if (end) {
            return;
        }

        appended.add(application);
        indirectly.add(application);
        Set<String> dependencies = registryContainer.getDependencies(application, reverse);
        if (dependencies != null && dependencies.size() > 0) {
            for (String dependency : dependencies) {
                appendDependency(rows, reverse, dependency, level + 1, appended, indirectly);
            }
        }
        appended.remove(application);
    }

}
